﻿using System;
using Sponsorship.Domain;
using Sponsorship.Domain.Sponsors;
using Sponsorship.Infrastructure;
using Sponsorship.ReadModel;
using Sponsorship.ReadModel.Sponsors;
using Sponsorship.Ui.Wpf.Commanding;
using Sponsorship.Ui.Wpf.Locator;
using Sponsorship.Ui.Wpf.Messaging;
using ICommand = System.Windows.Input.ICommand;

namespace Sponsorship.Ui.Wpf.ViewModel
{
    [Locator ("SponsorViewModel")]
    public class SponsorViewModel : ViewModelBase
    {
        private readonly IBus _bus;
        private RelayCommand _cancelCommand;
        private DetailsOfSponsorDto _detailModel;
        private readonly IReadRepository _readRepository;
        private RelayCommand _saveCommand;

        public SponsorViewModel (IBus bus, IReadRepository readRepository)
        {
            _bus = bus;
            _readRepository = readRepository;
        }

        public string AccountNumber
        {
            get { return _detailModel.BankInformation.AccountNumber; }
            set
            {
                if (_detailModel.BankInformation.AccountNumber == value) return;
                _detailModel.BankInformation.AccountNumber = value;
                RaisePropertyChanged ("AccountNumber");
            }
        }


        public string BankCode
        {
            get { return _detailModel.BankInformation.BankCode; }
            set
            {
                if (_detailModel.BankInformation.BankCode == value) return;
                _detailModel.BankInformation.BankCode = value;
                RaisePropertyChanged ("BankCode");
            }
        }

        public string Street
        {
            get { return _detailModel.Address.Street; }
            set
            {
                if (_detailModel.Address.Street == value) return;
                _detailModel.Address.Street = value;
                RaisePropertyChanged ("Street");
            }
        }

        public string Number
        {
            get { return _detailModel.Address.Number; }
            set
            {
                if (_detailModel.Address.Number == value) return;
                _detailModel.Address.Number = value;
                RaisePropertyChanged ("Number");
            }
        }

        public string Country
        {
            get { return _detailModel.Address.Country; }
            set
            {
                if (_detailModel.Address.Country == value) return;
                _detailModel.Address.Country = value;
                RaisePropertyChanged ("Country");
            }
        }

        public string City
        {
            get { return _detailModel.Address.City; }
            set
            {
                if (_detailModel.Address.City == value) return;
                _detailModel.Address.City = value;
                RaisePropertyChanged ("City");
            }
        }

        public string Zip
        {
            get { return _detailModel.Address.Zip; }
            set
            {
                if (_detailModel.Address.Zip == value) return;
                _detailModel.Address.Zip = value;
                RaisePropertyChanged("Zip");
            }
        }


        public ICommand CancelCommand
        {
            get
            {
                return _cancelCommand ?? (_cancelCommand = new RelayCommand (
                                                               param => Cancel(),
                                                               param => true
                                                               ));
            }
        }

        public string Comment
        {
            get { return _detailModel.Comment; }
            set
            {
                if (_detailModel.Comment == value) return;
                _detailModel.Comment = value;
                RaisePropertyChanged ("Comment");
            }
        }

        public string EMail
        {
            get { return _detailModel.EMail; }
            set
            {
                if (_detailModel.EMail == value) return;
                _detailModel.EMail = value;
                RaisePropertyChanged ("EMail");
            }
        }

        public string FirstName
        {
            get { return _detailModel.FirstName; }
            set
            {
                if (_detailModel.FirstName == value) return;
                _detailModel.FirstName = value;
                RaisePropertyChanged ("FirstName");
            }
        }

        public string LastName
        {
            get { return _detailModel.LastName; }
            set
            {
                if (_detailModel.LastName == value) return;
                _detailModel.LastName = value;
                RaisePropertyChanged ("LastName");
            }
        }


        public ICommand SaveCommand
        {
            get
            {
                return _saveCommand ?? (_saveCommand = new RelayCommand (
                                                           param => Save(),
                                                           param => CanSave
                                                           ));
            }
        }


        public string TelephoneNumber
        {
            get { return _detailModel.TelephoneNumber; }
            set
            {
                if (_detailModel.TelephoneNumber == value)
                    return;
                _detailModel.TelephoneNumber = value;
                RaisePropertyChanged ("TelephoneNumber");
            }
        }

        private bool CanSave
        {
            get
            {
                return
                    !String.IsNullOrEmpty (FirstName) &&
                    !String.IsNullOrEmpty (LastName);
            }
        }

        public override void SetModel (Guid id)
        {
            if (id != Guid.Empty)
            {
                _detailModel = _readRepository.GetById<DetailsOfSponsorDto>(Dto.GetDtoIdOf<DetailsOfSponsorDto>(id));
                _detailModel.BankInformation = _detailModel.BankInformation ?? new BankInformationDto();
                _detailModel.Address = _detailModel.Address ?? new AddressDto();
            }
            else
            {
                _detailModel = new DetailsOfSponsorDto();                
            }

            base.SetModel(id);

            RaisePropertyChanged("FirstName");
            RaisePropertyChanged("LastName");
            RaisePropertyChanged("EMail");
            RaisePropertyChanged("TelephoneNumber");
            RaisePropertyChanged("Comment");
            RaisePropertyChanged("AccountNumber");
            RaisePropertyChanged("BankCode");
            RaisePropertyChanged("Street");
            RaisePropertyChanged("Number");
            RaisePropertyChanged("Country");
            RaisePropertyChanged("City");
            RaisePropertyChanged("Zip");
        }

        private void Cancel()
        {
            Messenger.Instance.Send (this, "mainmenu");
        }

        private void Save()
        {
            bool newSponsor = _detailModel.AggregateRootId.ToString() == Guid.Empty.ToString();

            var bankInformation = new BankInformation(_detailModel.BankInformation.AccountNumber, _detailModel.BankInformation.BankCode, _detailModel.BankInformation.Iban, _detailModel.BankInformation.Swift);
            var address = new Address (_detailModel.Address.Street, _detailModel.Address.Number, _detailModel.Address.Zip, _detailModel.Address.City, _detailModel.Address.Country);

            if (newSponsor)
            {
                var command = new EnterSponsor (Guid.NewGuid(), _detailModel.FirstName, _detailModel.LastName, bankInformation, address, _detailModel.EMail, _detailModel.TelephoneNumber, _detailModel.Comment);
                _bus.Send (command);
            }
            else
            {
                var command = new ChangeSponsor (_detailModel.AggregateRootId, _detailModel.Version++, _detailModel.FirstName, _detailModel.LastName, bankInformation, address, _detailModel.EMail, _detailModel.TelephoneNumber, _detailModel.Comment);
                _bus.Send (command);
            }


            Cancel();
        }
    }
}